package com.ly.common.core.tool.security.utils;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.ly.common.core.constant.TokenConstants;
import com.ly.common.core.tool.security.config.properties.TokenProperties;
import com.ly.common.core.tool.security.entity.LyUser;
import com.ly.common.core.utils.RedisUtils;
import com.ly.common.core.utils.ServletUtils;
import com.ly.common.core.utils.SpringUtils;
import com.ly.common.core.utils.ip.AddressUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * token工具类
 */
public class TokenUtils {

    protected static final long MILLIS_SECOND = 1000;
    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;

    private static TokenProperties tokenProperties = SpringUtils.getBean(TokenProperties.class);
    private static RedisUtils redisUtils = SpringUtils.getBean(RedisUtils.class);



    /**
     * 删除用户身份信息
     */
    public static void delLoginUser(String uuid) {
        if (StrUtil.isNotEmpty(uuid)) {
            redisUtils.del(TokenConstants.LOGIN_TOKEN_KEY + uuid);
        }
    }

    /**
     * 创建令牌
     *
     * @param lyUser 用户信息
     * @return 令牌
     */
    public static String createToken(LyUser lyUser) {
        String uuid = IdUtil.fastUUID();
        lyUser.setUuid(uuid);
        // 设置代理
        UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
        String ip = ServletUtils.getClientIP();
        lyUser.setIpaddr(ip);
        lyUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
        lyUser.setBrowser(userAgent.getBrowser().getName());
        lyUser.setOs(userAgent.getOs().getName());
        refreshToken(lyUser);
        // 通过uuid生成token信息
        Map<String, Object> claims = new HashMap<>();
        claims.put(TokenConstants.LOGIN_USER_KEY, uuid);
        JWTSigner signer = JWTSignerUtil.hs512(tokenProperties.getSecret().getBytes());
        String token = JWTUtil.createToken(claims, signer);
        return token;
    }

    /**
     * 验证令牌有效期，相差不足20分钟，自动刷新缓存
     *
     * @param lyUser
     * @return 令牌
     */
    public static void verifyToken(LyUser lyUser) {
        long expireTime = lyUser.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
            refreshToken(lyUser);
        }
    }

    /**
     * 刷新令牌有效期-redis方式
     *
     * @param user 登录信息
     */
    public static void refreshToken(LyUser user) {
        user.setLoginTime(System.currentTimeMillis());
        user.setExpireTime(user.getLoginTime() + tokenProperties.getExpireTime() * MILLIS_MINUTE);
        // 根据uuid将loginUser缓存
        String key = TokenConstants.LOGIN_TOKEN_KEY + user.getUuid();
        redisUtils.set(key, user, tokenProperties.getExpireTime(), TimeUnit.MINUTES);
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    public static JSONObject parseToken(String token) {
        JWTSigner signer = JWTSignerUtil.hs512(tokenProperties.getSecret().getBytes());
        return JWTUtil.parseToken(token).setSigner(signer).getPayload().getClaimsJson();
    }

    public static String getUsernameFromToken(String token) {
        JSONObject claims = parseToken(token);
        return claims.getStr("sub");
    }

    public static void setLoginUser(LyUser lyUser) {
        if (ObjUtil.isNotNull(lyUser) && StrUtil.isNotEmpty(lyUser.getUuid())) {
            refreshToken(lyUser);
        }
    }
}
